package android.slc.extras.component.attchment.repository.remote;

import android.slc.appbase.api.slc.callback.SlcObserver;
import android.slc.appbase.api.slc.callback.po.SlcEntity;
import android.slc.appbase.api.slc.config.ApiConfig;
import android.slc.appbase.entity.ErrorMsg;
import android.slc.attachment.bean.Progress;
import android.slc.extras.component.attchment.entity.AttFileInfo;
import android.slc.extras.component.attchment.entity.Attachment;
import android.slc.extras.component.attchment.entity.StorageForm;
import android.slc.extras.component.attchment.utils.AttachmentItemUtils;
import android.slc.extras.component.attchment.utils.AttachmentUtils;
import android.slc.or.FileRequestBody;
import android.slc.or.SlcCallbackConfig;
import android.slc.or.SlcNu;
import android.slc.or.SlcParam;
import android.slc.rx.SlcRxJavaUtils;

import androidx.annotation.NonNull;

import com.blankj.utilcode.util.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import okhttp3.MultipartBody;

public class AttachmentServiceRepository {

    /**
     * 根据文件绝对路径格式化文件路径
     *
     * @param absolutePath
     * @return
     */
    public static String formatFilePathByAbsolutePath(String absolutePath) {
        return absolutePath;
    }

    public static String attachmentList2IdString(List<Attachment> attachmentList) {
        StringBuilder idsBuilder = new StringBuilder();
        CollectionUtils.forAllDo(attachmentList, (index, item) -> {
            if (item.isNetBody()) {
                idsBuilder.append(item.getNetBody().getId());
                idsBuilder.append(",");
            }
        });
        return idsBuilder.toString();
    }

    /**
     * 上传文件
     *
     * @param multipartBody
     * @return
     */
    public static Observable<SlcEntity<AttFileInfo>> uploadFile(MultipartBody multipartBody) {
        return SlcNu.getInstance().create(AttachmentService.class)
                .uploadFileByPart(multipartBody.parts().get(0));
        /*return SlcNu.getInstance().create(AttachmentService.class)
                .uploadFileByBody(multipartBody);*/
    }


    public static Observable<Attachment> uploadAttachmentListByFilter(Attachment attachment) {
        return uploadAttachmentListByFilter(Collections.singletonList(attachment));
    }

    public static Observable<Attachment> uploadAttachmentListByFilter(List<Attachment> attachmentList) {
        return uploadAttachmentList(AttachmentItemUtils.removeNetAttachment(attachmentList));
    }

    public static Observable<Attachment> uploadAttachment(Attachment attachment) {
        return uploadAttachmentList(Collections.singletonList(attachment));
    }

    /**
     * 递归上传文件
     *
     * @param attachmentList
     */
    public static Observable<Attachment> uploadAttachmentList(List<Attachment> attachmentList) {
        return Observable.create(new ObservableOnSubscribe<Attachment>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Attachment> emitter) {
                uploadAttachmentList(attachmentList, 0, emitter);
            }

            private void uploadAttachmentList(List<Attachment> attachmentList, int index, @NonNull ObservableEmitter<Attachment> emitter) {
                if (attachmentList.size() == index) {//当上传完最后一个附件时
                    for (Attachment attachment : attachmentList) {
                        if (!attachment.isNetBody()) {
                            //此处异常需自定义 暂时先这么写
                            emitter.onError(new IllegalStateException(ApiConfig.Value.RESULT_UPLOAD_FAILURE_MSG));
                            return;
                        }
                    }
                    emitter.onComplete();
                    return;
                }
                Attachment attachment = attachmentList.get(index);
                if (!attachment.isLocalBody()) {
                    uploadAttachmentList(attachmentList, index + 1, emitter);
                    return;
                }
                File attachmentFile = new File(attachment.getLocalPath());
                uploadFile(SlcParam.newBuilder()
                        .put("name", attachmentFile.getName())
                        .addPart(SlcParam.createPart("file", attachmentFile, new FileRequestBody.SimpleFileUploadListener() {
                            @Override
                            public void onProgressChange(int progress, long bytesWritten, long contentLength) {
                                Progress progressTemp = new Progress();
                                progressTemp.status = Progress.LOADING;
                                progressTemp.totalSize = contentLength;
                                progressTemp.fraction = progress;
                                attachment.setProgress(progressTemp);
                                emitter.onNext(attachment);
                            }
                        })).toMultipartBody())
                        .compose(SlcRxJavaUtils.applyOoAndroidSchedulers())
                        .subscribe(new SlcObserver<AttFileInfo>(SlcCallbackConfig.newBuilder().showDialog(false).showToast(false).build()) {
                            @Override
                            public void onStart() {
                                super.onStart();
                                Progress progressTemp = new Progress();
                                progressTemp.status = Progress.WAITING;
                                attachment.setProgress(progressTemp);
                                emitter.onNext(attachment);
                            }

                            @Override
                            public void onSucceed(AttFileInfo data) {
                                attachment.setNetBody(data);
                                Progress progressTemp = new Progress();
                                progressTemp.status = Progress.FINISH;
                                progressTemp.fraction = 100;
                                attachment.setProgress(progressTemp);
                                emitter.onNext(attachment);
                                uploadAttachmentList(attachmentList, index + 1, emitter);
                            }

                            @Override
                            public void onFailed(int errorCode, String errorMessage) {
                                Progress progressTemp = new Progress();
                                progressTemp.status = Progress.ERROR;
                                progressTemp.errorData = new ErrorMsg(errorCode, errorMessage);
                                attachment.setProgress(progressTemp);
                                emitter.onNext(attachment);
                                uploadAttachmentList(attachmentList, index + 1, emitter);
                            }
                        });
            }
        }).compose(SlcRxJavaUtils.applyOoAndroidSchedulers());

    }

    /**
     * 根据ids获取附件
     *
     * @param ids
     * @return
     */
    public static Observable<SlcEntity<List<Attachment>>> getAttachmentByIds(Long[] ids) {
        return SlcNu.getInstance().create(AttachmentService.class)
                .findListById(ids)
                .map(slcEntity -> {
                    List<Attachment> attachmentList = fileInfoToAttachment(slcEntity.getData());
                    SlcEntity<List<Attachment>> listSlcEntity = new SlcEntity<>();
                    listSlcEntity.setData(attachmentList);
                    listSlcEntity.setCode(slcEntity.getCode());
                    listSlcEntity.setMsg(slcEntity.getMsg());
                    return listSlcEntity;
                })
                .compose(SlcRxJavaUtils.applyOoAndroidSchedulers());
    }

    /**
     * 同步执行根据ids获取附件信息
     *
     * @param ids
     * @return
     */
    public static List<Attachment> getAttachmentByIdsSynchronous(Long[] ids) throws IOException {
        SlcEntity<List<AttFileInfo>> slcEntity = SlcNu.getInstance().create(AttachmentService.class)
                .findListByIdByCall(ids)
                .execute().body();
        if (slcEntity != null && slcEntity.isSuccess()) {
            return fileInfoToAttachment(slcEntity.getData());
        }
        return null;
    }

    /**
     * 文件信息转附件
     *
     * @param attFileInfoList
     * @return
     */
    public static List<Attachment> fileInfoToAttachment(List<AttFileInfo> attFileInfoList) {
        List<Attachment> attachmentList = new ArrayList<>();
        CollectionUtils.forAllDo(attFileInfoList, (index, item) -> {
            Attachment attachment = new Attachment(item);
            attachment.setIsAllowEditStatus(AttachmentUtils.IS_ALLOW_EDIT_STATUS_DISAGREE);
            attachmentList.add(attachment);
        });
        return attachmentList;
    }

    /**
     * storageFormList 2 attFileInfoList
     *
     * @param storageFormList
     * @return
     */
    public static List<AttFileInfo> storageFormToAttFileInfo(List<StorageForm> storageFormList) {
        List<AttFileInfo> attFileInfoList = new ArrayList<>();
        CollectionUtils.forAllDo(storageFormList, (index, item) -> {
            AttFileInfo attFileInfo = new AttFileInfo();
            attFileInfo.setNetBodyName(item.getLabel());
            attFileInfo.setNetBodyPath(item.getValue());
            attFileInfoList.add(attFileInfo);
        });
        return attFileInfoList;
    }

    public static List<Attachment> storageFormListToAttachment(List<StorageForm> storageFormList) {
        return fileInfoToAttachment(storageFormToAttFileInfo(storageFormList));
    }

    public static List<StorageForm> attachmentToStorageFormList(List<Attachment> attachmentList) {
        List<StorageForm> storageFormList = new ArrayList<>();
        CollectionUtils.forAllDo(attachmentList, (index, item) -> {
            StorageForm storageForm = new StorageForm();
            AttFileInfo attFileInfo = item.getNetBody();
            storageForm.setLabel(attFileInfo.getName());
            storageForm.setValue(attFileInfo.getNetBodyPath());
            storageFormList.add(storageForm);
        });
        return storageFormList;
    }
}